package com.newtouch.bxzs.database.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.newtouch.bxzs.common.base.BaseErrorEnum;
import com.newtouch.bxzs.common.base.BaseException;
import com.newtouch.bxzs.common.base.model.Role;
import com.newtouch.bxzs.common.base.model.RoleMenuButtonMap;
import com.newtouch.bxzs.common.base.model.RoleMenuMap;
import com.newtouch.bxzs.common.base.util.Assert;
import com.newtouch.bxzs.common.base.util.UserDetailUtil;
import com.newtouch.bxzs.database.constant.DataBaseConstant;
import com.newtouch.bxzs.database.mapper.*;
import com.newtouch.bxzs.database.model.bo.MenuButtonBO;
import com.newtouch.bxzs.database.model.bo.RoleBO;
import com.newtouch.bxzs.database.model.bo.RoleDetailBO;
import com.newtouch.bxzs.database.model.vo.*;
import com.newtouch.bxzs.database.service.RoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 角色Service实现类:
 *
 * <p>
 * <b>History:</b>
 * <table border="1">
 * <tr>
 * <th>Date</th>
 * <th>Operator</th>
 * <th>Memo</th>
 * </tr>
 * <tr>
 * <td>2021/1/4 14:20</td>
 * <td>zhangqianyang</td>
 * <td>Create</td>
 * </tr>
 * </table>
 *
 * @author zhangqianyang
 * @version 1.0.0
 * @since 1.0.0
 */
@Service
public class RoleServiceImpl implements RoleService {
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private ButtonMapper buttonMapper;
    @Resource
    private RoleMenuMapMapper roleMenuMapMapper;
    @Resource
    private RoleMenuButtonMapMapper roleMenuButtonMapMapper;
    @Resource
    private RolePositionMapMapper rolePositionMapMapper;

    /**
     * 查询角色列表信息
     *
     * @param roleListVO 查询参数
     * @return IPage < RoleBO> 分页结果
     */
    @Override
    public IPage<RoleBO> listRole(GetRoleListVO roleListVO) {

        // 分页查询
        Page<Role> page = new Page<>(roleListVO.getCurrentPage(), roleListVO.getPageSize());
        return roleMapper.selectRoleByPage(page, roleListVO.getKeyWord());

    }

    /**
     * 查询角色详情
     *
     * @param roleId 角色id
     * @return RoleDetailBO 角色详情
     */
    @Override
    public RoleDetailBO getRoleDetail(String roleId) {
        // 角色id不能为空
        Assert.notEmpty(roleId, "角色id不能为空");
        // 查询角色信息
        RoleDetailBO roleDetailBO = roleMapper.selectByRoleId(roleId);
        // 查询角色对应的菜单列表
        List<MenuButtonBO> menuList = buttonMapper.listButtonsByRoleId(roleId);
        roleDetailBO.setMenuList(menuList);
        return roleDetailBO;

    }

    /**
     * 添加/修改角色
     *
     * @param updateRoleVO 添加/修改角色参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(UpdateRoleVO updateRoleVO) {
        Assert.notEmpty(updateRoleVO, "参数不能为空");
        String operationType = updateRoleVO.getOperationType();
        Assert.notEmpty(operationType, "参数【操作类型】不能为空");
        // 新增或者修改
        if (DataBaseConstant.OPERATION_TYPE_1.equals(operationType)) {
            String roleName = updateRoleVO.getRoleName();
            String roleDescription = updateRoleVO.getRoleDescription();
            String roleId = updateRoleVO.getRoleId();
            List<MenuButtonVO> menuButtonList = updateRoleVO.getMenuIdList();
            // 参数角色名称不能为空
            Assert.notEmpty(roleName, "参数【角色名称】不能为空");
            // 参数角色描述不能为空
            Assert.notEmpty(roleDescription, "参数【角色描述】不能为空");
            Assert.notEmpty(updateRoleVO.getRoleCode(), "参数【角色编码】不能为空");
            Assert.notEmpty(updateRoleVO.getTerminalType(), "参数【角色所属终端类型】不能为空");

            Role role = new Role();
            BeanUtils.copyProperties(updateRoleVO, role);
            if (StringUtils.isBlank(roleId)) {
                // 新增角色
                role.setCreateUserId(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId());
                Date date = new Date();
                role.setCreateTime(date);
                role.setEnableFlag(false);
                role.setDeleteFlag(false);
                role.setUpdateTime(date);
                role.setUpdateUserId(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId());
                roleMapper.insert(role);
                roleId = role.getRoleId();

                // 如果菜单menuIdList不为空维护角色菜单中间表
                if (menuButtonList != null && !menuButtonList.isEmpty()) {
                    updateRoleMenuMap(roleId, menuButtonList);
                }
                return;
            }

            // 修改角色
            role.setUpdateUserId(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId());
            role.setUpdateTime(new Date());
            roleMapper.updateById(role);
            // 维护角色菜单中间表
            dealRoleMenuData(roleId, menuButtonList);

        }

        // 修改角色的授权
        if (DataBaseConstant.OPERATION_TYPE_2.equals(operationType)) {
            Assert.notEmpty(updateRoleVO.getRoleId(), "角色id不能为空");
            Assert.notEmpty(updateRoleVO.getMenuIdList(), "菜单id及对应按钮id不能为空");
            dealRoleMenuData(updateRoleVO.getRoleId(), updateRoleVO.getMenuIdList());
        }

    }

    /**
     * 启用/禁用角色
     *
     * @param updateStateVO 参数
     */
    @Override
    public void updateState(UpdateStateVO updateStateVO) {
        // 被使用的角色不能被禁用，查询岗位角色表中是否存在该角色
        if (DataBaseConstant.DISABLE.equals(updateStateVO.getEnableFlag()) &&
                null != rolePositionMapMapper.checkExistsByRoleId(updateStateVO.getServiceId())) {
            throw new BaseException(BaseErrorEnum.ENABLE_USE);
        }
        roleMapper.updateenableFlag(updateStateVO);
    }

    /**
     * 删除角色
     *
     * @param roleIdList 角色id
     */
    @Override
    public void deleteRole(List<String> roleIdList) {
        Assert.notEmpty(roleIdList, "参数【角色id】不能为空");
        // 判断要删除的角色是否都是禁用状态的角色
        int count = roleMapper.checkIsEnable(roleIdList);
        if (count < roleIdList.size()) {
            throw new BaseException(BaseErrorEnum.ENABLE_USE);
        }

        // 批量删除角色
        roleMapper.updateValidStatusById(roleIdList);

        // 批量删除角色菜单中间表中的数据
        roleMenuMapMapper.deleteByRoleIdBatch(roleIdList);

        // 批量删除角色菜单按钮中间表的数据
        roleMenuButtonMapMapper.deleteByRoleIdBatch(roleIdList);
    }

    /**
     * 查询全部角色
     *
     * @param getAllRoleVO 参数
     * @return List<RoleBO>
     */
    @Override
    public List<RoleBO> listAllRole(GetAllRoleVO getAllRoleVO) {
        // 参数校验
        Assert.notEmpty(getAllRoleVO, "参数不能为空");
        Assert.notEmpty(getAllRoleVO.getTerminalType(), "角色所属终端不能为空");
        // 查询
        return roleMapper.listAllRole(getAllRoleVO);
    }

    /**
     * 处理角色菜单中间表、角色菜单按钮中间表的数据（删除原来数据、插入新数据）
     */
    public void dealRoleMenuData(String roleId, List<MenuButtonVO> menuButtonList) {
        // 将ASSISTANT_ROLE_MENU中间表中原有的数据删除
        roleMenuMapMapper.deleteByRoleId(roleId);
        // 将ASSISTANT_ROLE_MENU_BUTTON_MAP中间表中的数据删除
        roleMenuButtonMapMapper.deleteByRoleId(roleId);
        // 不为空插入新的菜单和按钮
        if(menuButtonList != null && !menuButtonList.isEmpty()){
            // 维护 角色菜单中间表、角色菜单按钮中间表 表中的数据
            updateRoleMenuMap(roleId, menuButtonList);
        }

    }


    /**
     * 维护ASSISTANT_ROLE_MENU_MAP中间表和ASSISTANT_ROLE_MENU_BUTTON_MAP中间表
     *
     * @param roleId         角色id
     * @param menuButtonList 菜单id及对应的按钮id
     */
    public void updateRoleMenuMap(String roleId, List<MenuButtonVO> menuButtonList) {
        for (MenuButtonVO menuButtonVO : menuButtonList) {
            RoleMenuMap roleMenuMap = new RoleMenuMap();
            String menuId = menuButtonVO.getMenuId();
            roleMenuMap.setCreateUserId(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId());
            Date date = new Date();
            roleMenuMap.setCreateTime(date);
            roleMenuMap.setRoleId(roleId);
            roleMenuMap.setMenuId(menuId);
            // 角色菜单中间表插入
            roleMenuMapMapper.insert(roleMenuMap);

            // 菜单id对应的按钮id集合
            List<String> buttonIds = menuButtonVO.getButtonIds();
            if (buttonIds != null && !buttonIds.isEmpty()) {
                // 获取创建人id
                String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
                // 创建时间
                Date date1 = new Date();
                List<RoleMenuButtonMap> list = new ArrayList<>();
                for (String buttonId : buttonIds) {
                    // 维护角色菜单按钮中间表数据
                    RoleMenuButtonMap roleMenuButtonMap = new RoleMenuButtonMap();
                    roleMenuButtonMap.setCreateUserId(userId);
                    roleMenuButtonMap.setCreateTime(date1);
                    roleMenuButtonMap.setMenuId(menuId);
                    roleMenuButtonMap.setRoleId(roleId);
                    roleMenuButtonMap.setButtonId(buttonId);
                    list.add(roleMenuButtonMap);
                }
                // 角色菜单按钮中间表批量插入
                roleMenuButtonMapMapper.saveBatch(list);
            }
        }
    }
}
